package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.TsCache;
import com.atguigu.tingshu.common.config.redssion.RedissonConfig;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.base.BaseEntity;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.sound.midi.Track;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@SuppressWarnings({"all"})
@Transactional
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;
    @Autowired
	private AlbumStatMapper albumStatMapper;
    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;
	@Autowired
	private TrackInfoMapper trackInfoMapper;
	@Autowired
	private RabbitService rabbitService;
	@Autowired
	private RedissonClient redissonClient;
	@Autowired
	private RedisTemplate redisTemplate;
	@Override
	@Transactional
	public Boolean saveAlLbumInfo(AlbumInfoVo albumInfoVo, Long userId) {
		/*
			album_attribute_value
			album_info
			album_stat
		 */
		try {
			AlbumInfo albumInfo = new AlbumInfo();
			albumInfo.setUserId(userId);
			BeanUtils.copyProperties(albumInfoVo,albumInfo);
			//设置试听集数
			if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfoVo.getPayType())) {
				albumInfoVo.setTracksForFree(5);
			}
			albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
			albumInfoMapper.insert(albumInfo);
			List<AlbumAttributeValueVo> voList = albumInfoVo.getAlbumAttributeValueVoList();
			if (!CollectionUtils.isEmpty(voList)) {
				for (AlbumAttributeValueVo attribute : voList) {
					AlbumAttributeValue attributeValue = new AlbumAttributeValue();
					attributeValue.setAlbumId(albumInfo.getId());
					attributeValue.setAttributeId(attribute.getAttributeId());
					attributeValue.setValueId(attribute.getValueId());
                    albumAttributeValueMapper.insert(attributeValue);
				}
			}

			saveSta(albumInfo.getId(),SystemConstant.ALBUM_STAT_PLAY);
			saveSta(albumInfo.getId(),SystemConstant.ALBUM_STAT_SUBSCRIBE);
			saveSta(albumInfo.getId(),SystemConstant.ALBUM_STAT_BROWSE);
			saveSta(albumInfo.getId(),SystemConstant.ALBUM_STAT_COMMENT);
			//  判断当前专辑是公开; is_open=1;
			if ("1".equals(albumInfo.getIsOpen())){
				//  调用上架方法;
				rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_UPPER, albumInfo.getId());
				//添加布隆过滤器
				RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
				bloomFilter.add(albumInfo.getId());
			}
		} catch (BeansException e) {
			log.error(e.getMessage(),e);
			throw new GuiguException(ResultCodeEnum.SERVICE_ERROR);
		}
		return true;
	}
	public void saveSta(Long albumId,String stauType){
		AlbumStat albumStat = new AlbumStat();
		albumStat.setAlbumId(albumId);
		albumStat.setStatType(stauType);
		albumStat.setStatNum(new Random().nextInt(100000));
		albumStatMapper.insert(albumStat);
	}

	@Override
	public IPage<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> page, AlbumInfoQuery albumInfoQuery) {
		return albumInfoMapper.selectUserAlbumPage(page,albumInfoQuery);
	}

	@Override
	@TsCache(keyPrefix = RedisConstant.ALBUM_LOCK_SUFFIX)
	public AlbumInfo getAlbumInfo(Long albumId) {
//		String dataKey= RedisConstant.ALBUM_LOCK_SUFFIX+albumId;
//		try {
//			//根据缓存key获取数据
//			AlbumInfo albumInfo = (AlbumInfo) this.redisTemplate.opsForValue().get(dataKey);
//			//判断缓存中是否存在数据
//			if (null==albumInfo){
//				//不存在，查询数据库
//				//加锁
//				String lockKey = RedisConstant.ALBUM_LOCK_SUFFIX+albumId;
//				RLock lock = redissonClient.getLock(lockKey);
//				lock.lock();
//				try {
//					//查询数据库前，再确认一次缓存
//					albumInfo=(AlbumInfo)this.redisTemplate.opsForValue().get(dataKey);
//					if (null!=albumInfo){
//						return albumInfo;
//					}
//					//业务逻辑查询数据库
//					albumInfo= getAlbumInfoDB(albumId);
//					//判断数据是否为空
//					if (null==albumInfo){
//						//防止缓存穿透,设置一个空值
//						 this.redisTemplate.opsForValue()
//								 .set(dataKey,new AlbumInfo(), RedisConstant.ALBUM_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
//						 return new AlbumInfo();
//					}
//					//数据库中有数据
//					this.redisTemplate.opsForValue()
//							.set(dataKey,albumInfo, RedisConstant.ALBUM_TIMEOUT, TimeUnit.SECONDS);
//				} catch (Exception e) {
//					//异常信息
//					log.error(e.getMessage(),e);
//				} finally {
//					//解锁
//					lock.unlock();
//				}
//			}else {
//				//缓存中有数据
//				return albumInfo;
//			}
//		} catch (RuntimeException e) {
//			log.error(e.getMessage(),e);
//		}
		return getAlbumInfoDB(albumId);
	}

	private @Nullable AlbumInfo getAlbumInfoDB(Long albumId) {
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		if (null!= albumInfo) {
			LambdaQueryWrapper<AlbumAttributeValue> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(AlbumAttributeValue::getAlbumId, albumId);
			List<AlbumAttributeValue> valueList = albumAttributeValueMapper.selectList(wrapper);
			albumInfo.setAlbumAttributeValueVoList(valueList);
		}
		return albumInfo;
	}

	@Override
	@Transactional
	public void updateAlbumInfo(Long albumId, AlbumInfoVo albumInfoVo) {
		//保存info表（album_info）
		AlbumInfo albumInfo = new AlbumInfo();
		BeanUtils.copyProperties(albumInfoVo,albumInfo);
		albumInfo.setId(albumId);
		albumInfoMapper.updateById(albumInfo);
		//先删除再更新（album_attribute_value）
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().
				eq(AlbumAttributeValue::getAlbumId,albumId));
		List<AlbumAttributeValueVo> attributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		if (!CollectionUtils.isEmpty(attributeValueVoList)) {
			for (AlbumAttributeValueVo attributeValueVo : attributeValueVoList) {
				AlbumAttributeValue attributeValue = new AlbumAttributeValue();
				BeanUtils.copyProperties(attributeValueVo,attributeValue);
				attributeValue.setAlbumId(albumId);
				albumAttributeValueMapper.insert(attributeValue);
			}
		}
		//更新上架下架
		if ("1".equals(albumInfo.getIsOpen())){
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_UPPER,albumInfo.getId());
			//添加布隆过滤器
			RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
			bloomFilter.add(albumInfo.getId());
		}else {
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_LOWER,albumInfo.getId());
		}
	}

	@Override
	@Transactional
	public void removeAlbumInfo(Long albumId) {
		//查询专辑是否有声音
		LambdaUpdateWrapper<TrackInfo> wrapper = new LambdaUpdateWrapper<TrackInfo>().
				eq(TrackInfo::getAlbumId, albumId);
		Long count = trackInfoMapper.selectCount(wrapper);
		if (count>0) {
			throw new GuiguException(400,"该专辑下存在未删除声音");
		}
		//删除aLbum_info
		albumInfoMapper.deleteById(albumId);
		//删除 album_attribute_value;
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().
				eq(AlbumAttributeValue::getAlbumId,albumId));
		//删除统计信息、aLbum_stat
		albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId,albumId));
		//下架
		rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_LOWER,albumId);
	}

	@Override
	public List<AlbumInfo> findUserAllAlbumList(Long userId) {
		LambdaQueryWrapper<AlbumInfo> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(AlbumInfo::getUserId,userId);
		wrapper.orderByDesc(AlbumInfo::getId);
		Page<AlbumInfo> albumInfoPage = new Page<>(1, 100);
		Page<AlbumInfo> infoPage = albumInfoMapper.selectPage(albumInfoPage, wrapper);
		return infoPage.getRecords();
	}

	@Override
	public AlbumAttributeValue findAlbumAttributeValue(Long albumId) {
		LambdaQueryWrapper<AlbumAttributeValue> eq = new LambdaQueryWrapper<AlbumAttributeValue>().
				eq(AlbumAttributeValue::getAlbumId, albumId);
		AlbumAttributeValue attributeValue = albumAttributeValueMapper.selectOne(eq);
		return attributeValue;
	}

	@Override
	@TsCache(keyPrefix = "album:stat")
	public AlbumStatVo getAlbumStatVo(Long albumId) {
		return albumInfoMapper.selectAlbumStatVo(albumId);
	}
}